package com.yuntsg.ruiijn.controller.system;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RuntimeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.yuntsg.ruiijn.controller.admin.WosBasicController;
import com.yuntsg.ruiijn.database.entity.SysQueen;
import com.yuntsg.ruiijn.database.entity.WosBasic;
import com.yuntsg.ruiijn.database.mapper.PaperAnaTodoMapper;
import com.yuntsg.ruiijn.database.mapper.SysQueenMapper;
import com.yuntsg.ruiijn.database.mapper.WosBasicMapper;
import com.yuntsg.ruiijn.databse_search.entity.SearchRecord;
import com.yuntsg.ruiijn.databse_search.service.*;
import com.yuntsg.ruiijn.paperana.service.MatchService;
import com.yuntsg.ruiijn.paperana.utils.SmallTool;
import com.yuntsg.ruiijn.service.AsyncService;
import common.proxy.HttpUtil;
import common.util.*;
import common.vo.ContentsComparisonRes;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.tomcat.util.http.fileupload.RequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.yuntsg.ruiijn.service.AsyncService.localDateFilePath;

@Slf4j
@SuppressWarnings("ALL")
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TimeTaskService {


    private final WosBasicMapper basicMapper;
    private final InitController initController;
    private final WosBasicController wosBasicController;
    private final PaperAnaTodoMapper paperAnaTodoMapper;
    private final AsyncService asyncService;
    private final WosBasicMapper wosBasicMapper;
    private final FolderTypeService folderTypeService;
    private final SearchRecordService searchRecordService;
    private final FileDetailService fileDetailsService;
    private final SearchSelfService searchSelfService;
    private final BussService bussService;
    private final MinioUtil minioUtil;
    private final ImageComparison imageComparison;
    private final SysQueenMapper sysQueenMapper;
    private final ExtractUtil extractUtil;
    @Value("${upload.path}")
    public String uploadPath;
    @Resource
    MatchService matchService;

    /**
     * 将新上传的 WOS 文献自动获取全文链接和拆图片 上次任务完成后每 10 分钟 执行一次
     */
    @Scheduled(fixedDelay = 1000)
    public void GetPdfUrl() {
        if (VerifyUtil.isServer()) {
//            log.info("将新上传的 WOS 文献自动获取全文链接和拆图片");
            /**
             * 只看导入的文章
             * 6000
             */
            List<WosBasic> list = new LambdaQueryChainWrapper<>(basicMapper)
                    .select(WosBasic::getId, WosBasic::getPdfUrl, WosBasic::getSoType, WosBasic::getFileType, WosBasic::getFilePath, WosBasic::getCasesFlag, WosBasic::getCPm, WosBasic::getCUt, WosBasic::getCTi)
                    .eq(WosBasic::getSoType, 1)//只看 WOS 上传的文件
                    .ne(WosBasic::getCasesFlag, 1)
                    .isNull(WosBasic::getFilePath)
                    .orderByDesc(WosBasic::getId).last("limit 1000 ").list();

            //list = new LambdaQueryChainWrapper<>(basicMapper).isNull(WosBasic::getPdfUrl).between(WosBasic::getId, 1, 10).list();
            for (WosBasic wosBasic : list) {
                System.out.println("正在执行的 ID ___" + wosBasic.getId());
                /**
                 * 获取全文链接
                 */
                String abase64 = "";
                String newLink = "";
                String url = "";
                if (!StringUtil.isEmpty(wosBasic.getCPm())) {
                    abase64 = XXTEA.encryptToBase64StringNoSafe(wosBasic.getCPm(), "R0HWlCI3ndd1s8S3");
                    url = "https://www.pubtsg.com/api/getpdfurl.do?unitid=1&type=0&query=" + abase64;

                } else if (wosBasic.getCUt() != null) {
                    //abase64 = XXTEA.encryptToBase64StringNoSafe(wosBasic.getCUt().split(":")[1], "R0HWlCI3ndd1s8S3");
                    abase64 = XXTEA.encryptToBase64StringNoSafe(wosBasic.getCUt().split(":")[1], "R0HWlCI3ndd1s8S3");
                    url = "https://www.pubtsg.com/api/getpdfurl.do?unitid=1&type=1&query=" + abase64;
                }
//                System.out.println("PDF_URL___" + url);
                BasicCookieStore cookieStore = new BasicCookieStore();
                String html = HttpUtil.postHtmlQuanWen(cookieStore, url, "", "");

                Map<String, Object> map = new HashMap<String, Object>();
                map = JSON.parseObject(html, Map.class);
                if (map.get("pdfurl") != null) {//1094827  //40
                    String pdfUrl = (String) map.get("pdfurl");
//                    System.out.println("要存放的_PDF_URL___" + pdfUrl);
                    wosBasic.setFileType(1);
                    wosBasic.setPdfUrl(pdfUrl);
                    //设置全文文件路径
                    String fileName = wosBasic.getCTi().replaceAll(" +", "").trim();
                    fileName = RegexUtil.filterNAC(fileName);
                    String getpdfurl = PdfUtil.getpdfurl(wosBasic.getPdfUrl(), 1, 1);
//                    System.out.println("全文地址___" + getpdfurl);
                    BasicCookieStore basicCookieStore = new BasicCookieStore();
                    if (fileName.length() > 100) {
                        fileName = fileName.substring(0, 100);
                    }
                    String pdfPath = localDateFilePath() + fileName + ".PDF";
                    boolean flag = common.proxy.HttpUtil.DownPdfWithProxy(basicCookieStore, "https://attach.pubtsg.com/" + getpdfurl, "", uploadPath + pdfPath);
                    wosBasic.setFilePath(pdfPath);

                    {//设置图片数量
                        try {
                            int countPic = PDFCountUtil.getImgSum(uploadPath, pdfPath);
                            wosBasic.setPicCount(countPic);
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("PDF文件拆图片数量报错");
                        }
                    }

                    basicMapper.updateById(wosBasic);
                } else {
                    wosBasic.setCasesFlag(1);
                    basicMapper.updateById(wosBasic);
                }
            }
        }

    }

    /**
     * 超过一小时的列为分析失败 上次任务完成后每 1 分钟 执行一次
     */
    @Scheduled(fixedDelay = 100000)
    public void checkSuccess() throws IOException {
        if (VerifyUtil.isServer()) {
            long currentTimeMillis = System.currentTimeMillis();

            List<WosBasic> list = new LambdaQueryChainWrapper<>(basicMapper)
                    .select(WosBasic::getId, WosBasic::getAnalysisFlag, WosBasic::getAnalysisCount, WosBasic::getAnalysisTime)
                    .ne(WosBasic::getAnalysisTime, 0).eq(WosBasic::getAnalysisFlag, -1)//正在分析的
                    .list();

            for (WosBasic wosBasic : list) {
                Long analysisTime = wosBasic.getAnalysisTime();//早上十点
                if (analysisTime + 1000L * 60L * 60L < currentTimeMillis) {
                    wosBasic.setAnalysisFlag(-2);
                    System.out.println("数据" + wosBasic.getId() + "分析失败,更新当前状态");
                    wosBasicMapper.updateById(wosBasic);

                }
            }
        }
    }

    /**
     * 完成后三秒继续任务,当前分析任务 上次任务完成后每 3 秒钟 执行一次
     */
    @Scheduled(fixedDelay = 2000)
    public void paperAnalysis() throws IOException, InterruptedException {


//        SysQueen one = new LambdaQueryChainWrapper<>(sysQueenMapper).eq(SysQueen::getType, 1).eq(SysQueen::getStatus, 0).last(" limit 1").one();
//        if (one != null) {
//            one.setStatus(-1);
//            sysQueenMapper.updateById(one);
//            asyncService.check_pdf(one.getWosId(), one.getUid(), one.getId());
//        }

        if (VerifyUtil.isServer()) {
            ExecutorService executorService = Executors.newCachedThreadPool();
            CountDownLatch s = new CountDownLatch(5);
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                executorService.execute(() -> {
                    try {
                        SysQueen one = new LambdaQueryChainWrapper<>(sysQueenMapper).eq(SysQueen::getType, 1).eq(SysQueen::getStatus, 0).last(" limit 1").one();
                        if (one != null) {
                            System.out.println("开始执行新任务" + one.getWosId());
                            one.setStatus(-1);
                            sysQueenMapper.updateById(one);
                            asyncService.check_pdf(one.getWosId(), one.getUid(), one.getId());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    s.countDown();
                });
            }
            try {
                //阻塞当前线程，直到计数器的值为0
                s.await();
                executorService.shutdown();
            } catch (InterruptedException e) {
                SmallTool.printMessError("异常信息++" + e.getMessage());
            } finally {
                executorService.shutdown();

            }
        }


//        ThreadPoolExecutor executorService = new ThreadPoolExecutor(5, 15, 100, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10));
//        for (int i = 0; i < 5; i++) {
//            int a = i;
//            Thread.sleep(1000);
//            Runnable runnable = () -> {
//                try {
//                    SysQueen one = new LambdaQueryChainWrapper<>(sysQueenMapper).eq(SysQueen::getType, 1).eq(SysQueen::getStatus, 0).last(" limit 1").one();
//                    if (one!=null){
//                        one.setStatus(-1);
//                        sysQueenMapper.updateById(one);
//                        asyncService.check_pdf(one.getWosId(), one.getUid(), null);
//                    }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//
//            };
//            executorService.execute(runnable);
//        }
//        executorService.shutdown();

    }

    /**
     * 葛成瑞: 18678297353
     * 每隔十分钟处理查询表里面纯文字比对没有点击分析的进行自动分析
     */
//    @Scheduled(cron = "0 */10 * * * ?")
//    public void manualData() {
//
//        //十分钟查询自定义文字对比进行处理
////        log.error("处理自定义对比没处理的订单");
//        List<WosBasic> eq = new LambdaQueryChainWrapper<>(wosBasicMapper).eq(WosBasic::getDelFlag, 0).eq(WosBasic::getAnalysisFlag, 0).eq(WosBasic::getSoType, 2).list();
//        for (WosBasic wosBasic : eq) {
//            log.error("处理任务++wosBasic+" + wosBasic.getId());
//            wosBasic.setAnalysisFlag(-1);
//            wosBasicMapper.updateById(wosBasic);
//            // 进行处理
//            matchService.dealManualWordCheck(wosBasic);
//            wosBasicMapper.updateById(wosBasic);
//        }
//    }


    /**
     * 葛成瑞 每天21点重启重置正在分析的文字任务
     */
    @Scheduled(cron = "0 0 21 * * ?")
    public void ReStart() {
        List<WosBasic> eq = new LambdaQueryChainWrapper<>(wosBasicMapper).eq(WosBasic::getDelFlag, 0).eq(WosBasic::getTxtAnaFlag, -1).eq(WosBasic::getSoType, 2).list();
        for (WosBasic wosBasic : eq) {
            wosBasic.setTxtAnaFlag(0);
            wosBasicMapper.updateById(wosBasic);
        }
    }

//    @Scheduled(cron = "0/5 * * * * ? ")
//    public void ruijinTextStart() {
//        if (FileUtil.exist("/home/gcr/ruijin/")) {
////            log.info("瑞金版本进行每五秒查询重试");
//            List<WosBasic> eq = new LambdaQueryChainWrapper<>(wosBasicMapper).eq(WosBasic::getDelFlag, 0).eq(WosBasic::getSplitType, 2).isNull(WosBasic::getTxtAnaFlag).list();
//            List<WosBasic> eqDOing = new LambdaQueryChainWrapper<>(wosBasicMapper).eq(WosBasic::getDelFlag, 0).eq(WosBasic::getSplitType, 2).eq(WosBasic::getTxtAnaFlag, -1).list();
//            if (eqDOing.size() <= 5) {
//                if (eq.size() > 5) {
//                    List<WosBasic> wosBasics = eq.subList(0, 5);
//                    wosBasics.parallelStream().forEach(wosBasic -> {
//                        log.error("处理任务++wosBasic+" + wosBasic.getId());
//                        wosBasic.setTxtAnaFlag(-1);
//                        wosBasicMapper.updateById(wosBasic);
//                        // 进行处理
//                        matchService.dealManualWordCheck(wosBasic);
//                        wosBasicMapper.updateById(wosBasic);
//                    });
//                } else {
//                    eq.parallelStream().forEach(wosBasic -> {
//                        log.error("处理任务++wosBasic+" + wosBasic.getId());
//                        wosBasic.setTxtAnaFlag(-1);
//                        wosBasicMapper.updateById(wosBasic);
//                        // 进行处理
//                        matchService.dealManualWordCheck(wosBasic);
//                        wosBasicMapper.updateById(wosBasic);
//                    });
//                }
//            } else {
//                log.info("瑞金版本正在执行超过5个 稍后执行");
//            }
//        }
//    }

    /**
     * 葛成瑞 每天03点定时删除数据
     */
    @Scheduled(cron = "0 0 3 * * ? ")
    public void ReDel() {
        log.info("凌晨三点删除文件");
        String path = "/home/analysis/comparepdftemp/";
        List<File> allPathDic = FileUtils.getAllPathDic(path);
        for (File file1 : allPathDic) {
            FileUtil.del(file1);
        }
    }


    /**
     * 定时处理深度检索
     * 间隔5秒执行一次
     */
    @Scheduled(fixedDelay = 5000)
    public void deepSearch() {
        long count = searchRecordService.count(Wrappers.<SearchRecord>lambdaQuery().eq(SearchRecord::getStatus, 0));
        List<SearchRecord> list = searchRecordService.list(Wrappers.<SearchRecord>lambdaQuery().eq(SearchRecord::getStatus, 0).orderByAsc(SearchRecord::getCreateTime).last("limit 50"));
        if (list.size() > 0) {
//            log.info("执行定时任务深度检索, 数量：{}", list.size());
            list.stream().parallel().forEach(one -> {
                TimeInterval timer = DateUtil.timer();
                List<Integer> todoList = one.getTodoList();
                if (null == todoList || todoList.size() == 0) {
                    one.setTodoList(null).setFinishTime(System.currentTimeMillis()).setStatus(1).setReadStatus(-1);
                    searchRecordService.saveOrUpdate(one);
                    return;
                }
                Integer id = todoList.get(0);
                todoList.remove(id);

//                    List<ContentsComparisonRes> contentsComparisonRes = folderTypeService.anycGenRecodSingle(id, one.getUId(), one.getRId(), one.getId(), one.getTopk());
                try {
                    List<ContentsComparisonRes> contentsComparisonRes = folderTypeService.anycGenRecodSingle(id, one);
                    if (null != contentsComparisonRes) {
                        List<ContentsComparisonRes> jsonResult = one.getJsonResult();
                        if (null == jsonResult) {
                            jsonResult = new ArrayList<>();
                        }
                        jsonResult.add(contentsComparisonRes.get(0));
                        jsonResult = JSONArray.parseArray(JSONObject.toJSONString(jsonResult), ContentsComparisonRes.class).stream().sorted(Comparator.comparingDouble(ContentsComparisonRes::getMax).reversed()).collect(Collectors.toList());
                        one.setJsonResult(jsonResult);
                    } else {
                        todoList.add(id);
                    }
                } catch (Exception exception) {
                    todoList.add(id);
                    log.error("执行定时任务深度检索:{}_{} 出错,Exception：{}", one.getId(), id, exception.getMessage());
                } finally {
                    searchRecordService.saveOrUpdate(one.setTodoList(todoList));
                    log.info("执行定时任务深度检索:{}_{},耗时{} ms", one.getId(), id, timer.intervalRestart());
                }
            });
        }
    }

    /**
     * 每天3点 释放内存
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void releaseMemory() {
        RuntimeUtil.exec("service searchhub_local restart");
    }

    /**
     * 每天四点备份数据库
     *
     * @throws IOException
     */
    @Scheduled(cron = "0 0 4 * * ?")
    public void backups() throws IOException {
        String backconfigPath = "/home/back_sql/";
        String backpath = getPath() + backconfigPath;
        Calendar calendar = Calendar.getInstance();
        String date = "" + calendar.get(Calendar.YEAR) + (calendar.get(Calendar.MONTH) + 1) + calendar.get(Calendar.DATE);
        File targetFile = new File(backpath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        String[] cmd = new String[]{"/bin/sh", "-c", "/usr/bin/mysqldump -root -pquanfang3.1415 paper_analysis_local >" + backpath + date + ".sql"};
        Runtime.getRuntime().exec(cmd);
        System.out.println("执行完成");
    }

    /**
     * 需要的方法
     *
     * @return
     */
    private String getPath() {
        //服务器: tomcat/webapps/root
        //windows: 工作路径/项目名
        try {
            String root = RequestContext.class.getResource("/").getFile();
            return new File(root).getParentFile().getParentFile().getCanonicalPath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

/*
 else {
 if (wosBasic.getCasesFlag() == null) {
 Cases cases = new Cases();

 boolean nextFlag = true;

 if (!StringUtil.isEmpty(wosBasic.getCPm().trim())) {
 try {
 cases.setWeb(1);
 cases.setPmid(Integer.valueOf(wosBasic.getCPm().trim()));
 nextFlag = false;
 } catch (Exception e) {

 }
 }
 if (nextFlag) {
 cases.setWeb(8);
 cases.setMyid(wosBasic.getCUt().split(":")[1].trim());
 }

 cases.setUid(1);
 cases.setGid(1);
 cases.setPostdate(System.currentTimeMillis());
 cases.setTitle(wosBasic.getCTi());
 cases.setAuthor(wosBasic.getCAu());
 cases.setSourcefrom(wosBasic.getCSo());
 cases.setResult("全文处理中...");
 cases.setCnstatus(false);
 cases.setTypeid(0);
 cases.setStatus(0);
 cases.setDoi(wosBasic.getCDi());
 cases.setSourcecode("ZFL_SALE");
 // casesMapper.insert(cases);
 wosBasic.setCasesFlag(1);
 basicMapper.updateById(wosBasic);
 }
 }反馈
 */
